package com.leyou.item.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.vo.PageResult;
import com.leyou.item.dto.*;
import com.leyou.item.entity.Sku;
import com.leyou.item.entity.Spu;
import com.leyou.item.entity.SpuDetail;
import com.leyou.item.mapper.BrandMapper;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.SpuMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class GoodsService {

    @Autowired
    private SpuMapper spuMapper;

    @Autowired
    private SpuDetailMapper spuDetailMapper;

    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SkuMapper skuMapper;




    public PageResult<SpuDTO> querySpuByPage(Integer page, Integer rows, String key, Boolean saleable) {

        //1.分页
        PageHelper.startPage(page,rows);
        //2.搜索
        Example example = new Example(Spu.class);
        Example.Criteria criteria = example.createCriteria();
        //2.1 关键字搜索
        if (StringUtils.isNoneBlank(key)){
            criteria.andLike("name","%" +key +"%");
        }
        //2.2上下架过滤
        if (saleable !=null){
            criteria.andEqualTo("saleable",saleable);
        }
        //3.排序
        example.setOrderByClause("update_time DESC");
        //4.查询出结果
        List<Spu> spuList = spuMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(spuList)){
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        //5.封装并返回
        PageInfo<Spu> info = new PageInfo<>(spuList);
        List<SpuDTO> spuDTOS = BeanHelper.copyWithCollection(spuList, SpuDTO.class);
        handleCategoryAndBrandName(spuDTOS);
        return new PageResult<>(info.getTotal(),spuDTOS);
    }

    private void handleCategoryAndBrandName(List<SpuDTO> spuDTOS) {

        for (SpuDTO spuDTO : spuDTOS) {
            // 查询分类名称
            List<CategoryDTO> category = categoryService.queryByIds(spuDTO.getCategoryIds());
            /*StringBuilder sb = new StringBuilder();
            for (CategoryDTO dto : category) {
                sb.append(dto.getName()).append("/");
            }
            sb.deleteCharAt(sb.length() -1 );*/
            String name = category.stream().map(CategoryDTO::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(name);
            //查询品牌名称

            BrandDTO brand = brandService.queryById(spuDTO.getBrandId());
            spuDTO.setBrandName(brand.getName());
        }

    }

    @Transactional
    public void saveGoods(SpuDTO spuDTO) {
        // 从dto中取出spu信息
        Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);
        // 保存spu
        spu.setId(null);
        spu.setCreateTime(null);
        spu.setSaleable(null);

        int count = spuMapper.insertSelective(spu);
        if (count != 1){
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }

        // 初始化SpuDetail信息
        SpuDetailDTO spuDetail = spuDTO.getSpuDetail();
        SpuDetail detail = BeanHelper.copyProperties(spuDetail, SpuDetail.class);
        detail.setSpuId(spu.getId());
        // 保存spu详情
        count = spuDetailMapper.insertSelective(detail);
        if (count != 1){
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }


        // 准备sku数据
        List<SkuDTO> skus = spuDTO.getSkus();
        List<Sku> skuList = new ArrayList<>();
        for (SkuDTO skuDTO : skus) {
            skuDTO.setSpuId(spu.getId());
            skuList.add(BeanHelper.copyProperties(skuDTO,Sku.class));
        }
        // 保存sku
        count = skuMapper.insertList(skuList);
        if (count != skuList.size()){
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }

    }
    @Autowired
    private AmqpTemplate amqpTemplate;

    @Transactional
    public void updateSpuSaleable(Long id, Boolean saleable) {
        // 修改spu
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        int count = spuMapper.updateByPrimaryKeySelective(spu);
        if (count != 1){
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }

        // 顺便把sku中的enable也修改了
        Example example = new Example(Sku.class);
        example.createCriteria().andEqualTo("spuId",id);
        Sku sku = new Sku();
        sku.setEnable(saleable);
        skuMapper.updateByExampleSelective(sku,example);

        String routingkey = saleable ? MQConstants.RoutingKey.ITEM_UP_KEY : MQConstants.RoutingKey.ITEM_DOWN_KEY;
        amqpTemplate.convertAndSend(MQConstants.Exchange.ITEM_EXCHANGE_NAME,routingkey,id);
    }






    public SpuDetailDTO querySpuDetailById(Long id) {

        SpuDetail spuDetail = spuDetailMapper.selectByPrimaryKey(id);
        if (spuDetail == null){

            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }

        return BeanHelper.copyProperties(spuDetail,SpuDetailDTO.class);

    }






    public List<SkuDTO> querySkuBySpuId(Long id) {

        Sku sku = new Sku();
        sku.setSpuId(id);
        List<Sku> skus = skuMapper.select(sku);

        if (CollectionUtils.isEmpty(skus)){

            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }

        return BeanHelper.copyWithCollection(skus,SkuDTO.class);

    }







    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
        // 修改spu
        Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);
        spu.setCreateTime(null);
        spu.setSaleable(null);

        int count = spuMapper.updateByPrimaryKeySelective(spu);
        if (count != 1){
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
        // 修改spuDetail
        SpuDetailDTO spuDetail = spuDTO.getSpuDetail();
        SpuDetail detail = BeanHelper.copyProperties(spuDetail, SpuDetail.class);
        count = spuDetailMapper.updateByPrimaryKeySelective(detail);
        if (count != 1){
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }

        //删除sku数据
        Sku sku = new Sku();
        sku.setSpuId(spuDTO.getId());
        count = skuMapper.delete(sku);
        if (count < 1){
            throw new LyException(ExceptionEnum.DELETE_OPERATION_FAIL);
        }
        // 新增sku
        List<SkuDTO> skus = spuDTO.getSkus();
        List<Sku> skuList = new ArrayList<>();

        for (SkuDTO skuDTO : skus) {
            skuDTO.setSpuId(spuDTO.getId());
            skuList.add(BeanHelper.copyProperties(skuDTO,Sku.class));
        }
        // 保存sku
        count = skuMapper.insertList(skuList);
        if ( count != skuList.size()){
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }

    }






    public SpuDTO querySpuById(Long id) {
        //查询sku
        Spu spu = spuMapper.selectByPrimaryKey(id);
        if (spu==null){
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }


        SpuDTO spuDTO = BeanHelper.copyProperties(spu, SpuDTO.class);
        //查询spuDetail
        spuDTO.setSpuDetail(querySpuDetailById(id));
        //查询sku
        spuDTO.setSkus(querySkuBySpuId(id));


        return spuDTO;
    }

    public List<SkuDTO> querySkuByListIds(List<Long> ids) {

        List<Sku> skuList = skuMapper.selectByIdList(ids);
        if (CollectionUtils.isEmpty(skuList)){
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }

        return BeanHelper.copyWithCollection(skuList,SkuDTO.class);
    }

    public void minusStock(Map<Long, Integer> cartMap) {

        try {
            for (Map.Entry<Long, Integer> entry : cartMap.entrySet()) {
                Long id = entry.getKey();
                Integer sum = entry.getValue();
                int count = skuMapper.minusStock(id,sum);
                if (count != 1){
                    throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
                }
            }
        } catch (LyException e) {
            throw new LyException(ExceptionEnum.STOCK_NOT_ENOUGH);
        }

    }
}
